// nvue操作dom的库，用于获取dom的尺寸信息
const dom = uni.requireNativePlugin('dom');
const bindingX = uni.requireNativePlugin('bindingx');
const animation = uni.requireNativePlugin('animation');

export default {
    data() {
        return {
            // 所有按钮的总宽度
            buttonsWidth: 0,
            // 是否正在移动中
            moving: false
        }
    },
    computed: {
        // 获取过渡时间
        getDuratin() {
            let duration = String(this.duration)
            // 如果ms为单位，返回ms的数值部分
            if (duration.indexOf('ms') >= 0) return parseInt(duration)
            // 如果s为单位，为了得到ms的数值，需要乘以1000
            if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000
            // 如果值传了数值，且小于30，认为是s单位
            duration = Number(duration)
            return duration < 30 ? duration * 1000 : duration
        }
    },
    watch: {
        show(n) {
            if (n) {
                this.moveCellByAnimation('open')
            } else {
                this.moveCellByAnimation('close')
            }
        }
    },
    mounted() {
        this.initialize()
    },
    methods: {
        initialize() {
            this.queryRect()
        },
        // 关闭单元格，用于打开一个，自动关闭其他单元格的场景
        closeHandler() {
            if (this.status === 'open') {
                // 如果在打开状态下，进行点击的话，直接关闭单元格
                return this.moveCellByAnimation('close') && this.unbindBindingX()
            }
        },
        // 点击单元格
        clickHandler() {
            // 如果在移动中被点击，进行忽略
            if (this.moving) return
            // 尝试关闭其他打开的单元格
            this.parent && this.parent.closeOther(this)
            if (this.status === 'open') {
                // 如果在打开状态下，进行点击的话，直接关闭单元格
                return this.moveCellByAnimation('close') && this.unbindBindingX()
            }
        },
        // 滑动单元格
        onTouchstart(e) {
            // 如果当前正在移动中，或者disabled状态，则返回
            if (this.moving || this.disabled) {
                return this.unbindBindingX()
            }
            if (this.status === 'open') {
                // 如果在打开状态下，进行点击的话，直接关闭单元格
                return this.moveCellByAnimation('close') && this.unbindBindingX()
            }
            // 特殊情况下，e可能不为一个对象
            e?.stopPropagation && e.stopPropagation()
            e?.preventDefault && e.preventDefault()
            this.moving = true
            // 获取元素ref
            const content = this.getContentRef()
            let expression = `min(max(${-this.buttonsWidth}, x), 0)`
            // 尝试关闭其他打开的单元格
            this.parent && this.parent.closeOther(this)

            // 阿里为了KPI而开源的BindingX
            this.panEvent = bindingX.bind({
                anchor: content,
                eventType: 'pan',
                props: [{
                    element: content,
                    // 绑定width属性，设置其宽度值
                    property: 'transform.translateX',
                    expression
                }]
            }, (res) => {
                this.moving = false
                if (res.state === 'end' || res.state === 'exit') {
                    const deltaX = res.deltaX
                    if (deltaX <= -this.buttonsWidth || deltaX >= 0) {
                        // 如果触摸滑动的过程中，大于单元格的总宽度，或者大于0，意味着已经动过滑动达到了打开或者关闭的状态
                        // 这里直接进行状态的标记
                        this.$nextTick(() => {
                            this.status = deltaX <= -this.buttonsWidth ? 'open' : 'close'
                        })
                    } else if (Math.abs(deltaX) > uni.$u.getPx(this.threshold)) {
                        // 在移动大于阈值、并且小于总按钮宽度时，进行自动打开或者关闭
                        // 移动距离大于0时，意味着需要关闭状态
                        if (Math.abs(deltaX) < this.buttonsWidth) {
                            this.moveCellByAnimation(deltaX > 0 ? 'close' : 'open')
                        }
                    } else {
                        // 在小于阈值时，进行关闭操作(如果在打开状态下，将不会执行bindingX)
                        this.moveCellByAnimation('close')
                    }
                }
            })
        },
        // 释放bindingX
        unbindBindingX() {
            // 释放上一次的资源
            if (this?.panEvent?.token != 0) {
                bindingX.unbind({
                    token: this.panEvent?.token,
                    // pan为手势事件
                    eventType: 'pan'
                })
            }
        },
        // 查询按钮节点信息
        queryRect() {
            // 历遍所有按钮数组，通过getRectByDom返回一个promise
            const promiseAll = this.options.map((item, index) => {
                return this.getRectByDom(this.$refs[`u-swipe-action-item__right__button-${index}`][0])
            })
            // 通过promise.all方法，让所有按钮的查询结果返回一个数组的形式
            Promise.all(promiseAll).then(sizes => {
                this.buttons = sizes
                // 计算所有按钮总宽度
                this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0)
            })
        },
        // 通过nvue的dom模块，查询节点信息
        getRectByDom(ref) {
            return new Promise(resolve => {
                dom.getComponentRect(ref, res => {
                    resolve(res.size)
                })
            })
        },
        // 移动单元格到左边或者右边尽头
        moveCellByAnimation(status = 'open') {
            if (this.moving) return
            // 标识当前状态
            this.moveing = true
            const content = this.getContentRef()
            const x = status === 'open' ? -this.buttonsWidth : 0
            animation.transition(content, {
                styles: {
                    transform: `translateX(${x}px)`,
                },
                duration: uni.$u.getDuration(this.duration, false),
                timingFunction: 'ease-in-out'
            }, () => {
                this.moving = false
                this.status = status
                this.unbindBindingX()
            })
        },
        // 获取元素ref
        getContentRef() {
            return this.$refs['u-swipe-action-item__content'].ref
        },
        beforeDestroy() {
            this.unbindBindingX()
        }
    }
}
